#include "HIDPS2conv.h"
#include "BleManager.h"

#define DEBUG_LOG

HIDPS2conv_HIDPoint HIDPS2conv::s_hidPoint[HID_COUNT];

void HIDPS2conv::ble_onConnect(BleServerConnector *pBleServerConnector, BLERemoteService *pRemoteService, bool &flag) {

    flag = false;

    for (int i = 0; i < HID_COUNT; i++) {
        HIDPS2conv_HIDPoint &hidPt = s_hidPoint[i];
        if (hidPt.type == 1 && hidPt.pBleServerConnector == pBleServerConnector) {

            // 设置协议模式为Report（默认是Boot Protocol）
            BLERemoteCharacteristic *pProtocolModeChar = pRemoteService->getCharacteristic(BLE_SERVER_CHAR_UUID_UUID_2A4E);
            if (pProtocolModeChar == nullptr) {
                return;
            } else {
                uint8_t mode = 0x01; // Report Protocol
                pProtocolModeChar->writeValue(&mode, 1);
            }

            if (!hidPt.hid._bInit) {
                // 查找报表描述符的特征
                BLERemoteCharacteristic *pReportMapChar = pRemoteService->getCharacteristic(BLE_SERVER_CHAR_UUID_UUID_2A4B);
                if (pReportMapChar == nullptr) {
                    // 没有找到目标服务的特征UUID
                    return;
                }

                // 读取并分析报表描述符
                Serial.println("analyzeReportMap");
                std::string s = pReportMapChar->readValue();
                if (s.length() == 0) {
                    return;
                }

                hidPt.hid.init((uint8_t *)s.data(), s.length());
            }
            flag = true;
            break;
        }
    }
}

void HIDPS2conv::ble_onDisconnect(BleServerConnector *pBleServerConnector) {
    for (int i = 0; i < HID_COUNT; i++) {
        HIDPS2conv_HIDPoint &hidPt = s_hidPoint[i];
        if (hidPt.pBleServerConnector == pBleServerConnector) {
            hidPt.pReadReportCharacteristic = nullptr;
            break;
        }
    }
}

void HIDPS2conv::ble_bindReadReportCharacteristic(BleServerConnector *pBleServerConnector, BLERemoteCharacteristic *pCharacteristic) {
    for (int i = 0; i < HID_COUNT; i++) {
        HIDPS2conv_HIDPoint &hidPt = s_hidPoint[i];
        if (hidPt.pBleServerConnector == pBleServerConnector) {
            hidPt.pReadReportCharacteristic = pCharacteristic;
            break;
        }
    }
}

void HIDPS2conv::onRecvDataHID(int num, uint8_t *dataBuf, int nLen) {
#if defined DEBUG_LOG
    Serial.printf("#%d:", num);
    printHex(dataBuf, nLen);
    Serial.println();
#endif
}

HIDPS2conv_HIDPoint *HIDPS2conv::addHidDevice(BleServerConnector *pConnector) {
    for (int i = 0; i < HID_COUNT; i++) {
        HIDPS2conv_HIDPoint &hidPt = s_hidPoint[i];
        if (hidPt.type == 0) {
            hidPt.pBleServerConnector = pConnector;
            hidPt.type = 1;
            hidPt.keyboard_mode = pConnector->_keyboard_mode;
            return &hidPt;
        }
    }
    return nullptr;
}

HIDPS2conv_HIDPoint *HIDPS2conv::addHidDevice(USBClientConnector *pConnector) {

    uint8_t tryTime = 20;
    for (int i = 0; i < HID_COUNT; i++) {
        HIDPS2conv_HIDPoint *pHhidPt = &s_hidPoint[i];
        if (pHhidPt->type == 0) {
            pHhidPt->pUSBClientConnector = pConnector;
            pHhidPt->type = 2;
            pHhidPt->keyboard_mode = pConnector->_keyboard_mode;

            // 获取HID设备报表描述符
            uint8_t data[8];
            memcpy(data, SetupHIDGetReportDescr, 8);
            data[6] = pConnector->hidReportDescLen;

            while (tryTime--) {
                int len;
                uint8_t *pData = _SUSB.usbSetupIn(pConnector->usbNum, data, data[6], &len);

                // 分析报表描述符
                if (len) {
                    Serial.printf("tryTime:%d\n", 20 - tryTime);
                    pHhidPt->hid.init(pData, len);
                    delete[] pData;
                    break;
                }
            }

            return pHhidPt;
        }
    }

    return nullptr;
}

void HIDPS2conv::removeHidDevice(BleServerConnector *pConnector) {
    for (int i = 0; i < HID_COUNT; i++) {
        HIDPS2conv_HIDPoint &hidPt = s_hidPoint[i];
        if (hidPt.pBleServerConnector == pConnector) {
            hidPt.type = 0;
            hidPt.pBleServerConnector = nullptr;
            hidPt.pReadReportCharacteristic = nullptr;
            hidPt.hid.destory();
            break;
        }
    }
}

void HIDPS2conv::removeHidDevice(USBClientConnector *pConnector) {
    for (int i = 0; i < HID_COUNT; i++) {
        HIDPS2conv_HIDPoint &hidPt = s_hidPoint[i];
        if (hidPt.pUSBClientConnector == pConnector) {
            hidPt.type = 0;
            hidPt.pUSBClientConnector = nullptr;
            hidPt.hid.destory();
            break;
        }
    }
}